﻿// alpha_test.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "alpha_test.h"
#include "colordef.h"
#include <time.h>

//////////////////////////////////////////////////////////////////////////

static BOOL g_FullScr;
static UINT g_Timer;
static UINT g_Fps = 1000;
static SIZE g_Size;
static HANDLE g_Thread;
static LARGE_INTEGER g_Freq;
static LARGE_INTEGER g_StartTime;
static QWORD g_LastTick;

static BOOL g_End;
static CRITICAL_SECTION g_Lock;

static ATOM MyRegisterClass(HINSTANCE hInstance);
static BOOL InitInstance(HINSTANCE, int);
static VOID Draw(VOID);
static INT OnEnter(VOID);
static INT OnSpace(VOID);
static INT OnDel(VOID);
static INT OnEscape(VOID);
static INT OnF1(VOID);
static INT OnF2(VOID);
static INT OnF3(VOID);
static INT OnAltEnter(VOID);
static BOOL OnMinimize(VOID);
static BOOL OnMaximize(VOID);
static BOOL OnRestore(VOID);
static INT OnTimer(VOID);
static INT OnQuit(VOID);
static VOID InitAlpha(VOID);
static VOID UpdateImage(VOID);
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static DWORD WINAPI DrawThread(LPVOID lpParameter);

//////////////////////////////////////////////////////////////////////////
// 绘制方块临界区变量

struct BOX
{
	RECT		rect;		// 盒子矩形
	COLORREF	color;		// 盒子颜色，带ALPHA
							// 仅当alpha成员不为NULL时使用
	SIZE		move;		// 前进方向和速度
							// 8个方向，cx为正表示x正方向，以此类推
							// cx, cy的绝对值为该方向上的移动速度（像素数）
	INT			ac;			// ALPHA变化量
};

static BOOL g_ShowBox = FALSE;
static INT g_MaxBox = 8;

static BOX g_Box[1000] =
{
	// rect					  color					    move		 ac	
	{ { 100, 100, 250, 250 }, RGBA(255, 255, 255, 200), {  17, -19 }, -3 },
	{ { 200, 200, 400, 400 }, RGBA(  0, 128, 255,  77), {  -7, -11 },  7 },
	{ { 150, 350, 270, 470 }, RGBA(128, 128, 128,  44), {  -9,  11 }, -1 },
	{ { 250,  50, 340, 140 }, RGBA(  0, 255,  64, 128), {  17,  13 },  3 },
	{ { 300, 150, 350, 200 }, RGBA(255, 0,   255, 133), { -23,   2 }, -5 },
	{ { 220, 220, 350, 350 }, RGBA( 64,  64, 128, 233), {  17,   3 }, -9 },
	{ {  50, 150, 300, 400 }, RGBA(  0,   0, 197,  32), {  -5,  23 },  1 },
	{ { 180, 350, 280, 450 }, RGBA(128,  64,  64, 180), { -11, -13 }, 11 },
};

static CRITICAL_SECTION g_LockBox;

//////////////////////////////////////////////////////////////////////////
// 绘制图像临界区变量

#define MAX_PIC_NUM		8
#define MAX_PIC_WIDTH	200
#define MAX_PIC_HEIGHT	200

struct PIC
{
	RECT		rect;		// 图像矩形
	COLORREF	color;		// 图像颜色，不带ALPHA
	SIZE		move;		// 前进方向和速度
							// 8个方向，cx为正表示x正方向，以此类推
							// cx, cy的绝对值为该方向上的移动速度（像素数）
	COLORREF	cc;			// 颜色变化量	// TODO: 未实现
	INT			ac;			// ALPHA变化量	// TODO: 未实现
	LPVOID		image;		// 图像数据
	UINT		ipitch;		// 图像的Pitch
	LPVOID		alpha;		// ALPHA数据
	UINT		apitch;		// ALPHA的Pitch
};

static BOOL g_ShowPic = TRUE;
static WORD g_Image[MAX_PIC_NUM][MAX_PIC_HEIGHT][MAX_PIC_WIDTH];
static BYTE g_Alpha[MAX_PIC_NUM][MAX_PIC_HEIGHT][MAX_PIC_WIDTH];

static INT g_MaxPic = 8;

static PIC g_Pic[1000] =
{
	// rect					  color				  move		    cc				  ac	
	{ { 100, 100, 220, 260 }, RGB(255, 255, 255), {  13,  -1 }, RGB( -3,   0,   1), -3 },
	{ { 200, 200, 400, 400 }, RGB(  0, 128, 255), {  19,   5 }, RGB(  1,  -2,   5),  7 },
	{ { 155, 350, 255, 450 }, RGB(128, 128, 128), {  -3, -21 }, RGB(  7,  11,  -7), -1 },
	{ { 250,  60, 350, 160 }, RGB(  0, 255,  64), {  11,  -9 }, RGB( -4, -13,  -1),  3 },
	{ { 300, 150, 380, 250 }, RGB(255, 0,   255), {  23,  -2 }, RGB( 11,  -5,  17), -5 },
	{ { 220, 220, 320, 320 }, RGB( 64,  64, 128), {  -7,   5 }, RGB( 23,  -3,   2), -9 },
	{ {  50, 150, 250, 350 }, RGB(  0,   0, 197), {  -3, -13 }, RGB( -1,   5, -19),  1 },
	{ { 180, 350, 280, 450 }, RGB(128,  64,  64), {  11, -19 }, RGB(-11,  17,   3), 11 },
};

static CRITICAL_SECTION g_LockPic;

//////////////////////////////////////////////////////////////////////////
// 绘制渐变ALPHA矩形临界区变量

static BOOL g_ShowALv = TRUE;

WORD g_ALvImage[256][256];
BYTE g_ALvAlpha[256][256];

static PIC g_ALvBox =
{
	{ 200, 200, 456, 456 },		// rect
	RGB(255, 0, 0),				// color
	{ 0, 0 },					// move
	RGB(0, 0, 0),				// cc
	0,							// ac
	g_ALvImage,					// image
	512,						// ipitch
	g_ALvAlpha,					// alpha
	256,						// apitch
};

static CRITICAL_SECTION g_LockALv;

//////////////////////////////////////////////////////////////////////////

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	MSG msg;

	// Initialize global strings
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance(hInstance, nCmdShow))
		return FALSE;

	// 启动绘制线程
	g_Thread = CreateThread(NULL, 0, DrawThread, NULL, THREAD_QUERY_INFORMATION, 0);

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, NULL, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	DeleteCriticalSection(&g_LockALv);
	DeleteCriticalSection(&g_LockPic);
	DeleteCriticalSection(&g_LockBox);
	DeleteCriticalSection(&g_Lock);
	ExitDD();

	return (int)msg.wParam;
}

//////////////////////////////////////////////////////////////////////////

static ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASS wc;

	wc.style			= CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc		= WndProc;
	wc.cbClsExtra		= 0;
	wc.cbWndExtra		= 0;
	wc.hInstance		= hInstance;
	wc.hIcon			= NULL;
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName		= NULL;
	wc.lpszClassName	= _T("AlphaTest");

	return RegisterClass(&wc);
}

static BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	HWND hWnd;
	RECT rect;
	DWORD style;

	srand(static_cast<UINT>(time(NULL)));

	style = WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX;

	rect.left = 0;
	rect.right = 800;
	rect.top = 0;
	rect.bottom = 600;

	if (!AdjustWindowRect(&rect, style, FALSE))
		return FALSE;

	hWnd = CreateWindow(_T("AlphaTest"), _T("Alpha Test"), style, CW_USEDEFAULT, 0,
		rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hInstance, NULL);

	if (!hWnd)
		return FALSE;

	g_FullScr = FALSE;

	if (!InitDD(hWnd, g_FullScr))
	{
		ExitDD();
		return FALSE;
	}

	if (!GetClientRect(hWnd, &rect))
		return FALSE;

	g_Size.cx = rect.right - rect.left;
	g_Size.cy = rect.bottom - rect.top;

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	if (!QueryPerformanceFrequency(&g_Freq))
		return FALSE;

	if (!QueryPerformanceCounter(&g_StartTime))
		return FALSE;

	g_Timer = static_cast<UINT>(SetTimer(hWnd, 1, 50, NULL));

	g_End = FALSE;
	InitializeCriticalSection(&g_Lock);
	InitializeCriticalSection(&g_LockBox);
	InitializeCriticalSection(&g_LockPic);
	InitializeCriticalSection(&g_LockALv);

	InitAlpha();
	UpdateImage();

	return TRUE;
}

static VOID Draw(VOID)
{
	INT i;
	INT max_num;
	BOOL show;
	BOX box;
	PIC *pic;

	if (!BeginDraw())
		return;

	i = 0;
	while (1) {

		EnterCriticalSection(&g_LockBox);
		show = g_ShowBox;
		LeaveCriticalSection(&g_LockBox);

		if (!show)
			break;

		EnterCriticalSection(&g_LockBox);
		max_num = g_MaxBox;
		LeaveCriticalSection(&g_LockBox);

		if (i >= max_num)
			break;

		EnterCriticalSection(&g_LockBox);
		box = g_Box[i];
		LeaveCriticalSection(&g_LockBox);

		DrawRectangle(&box.rect, box.color);

		i++;
	}

	i = 0;
	while (1) {

		EnterCriticalSection(&g_LockPic);
		show = g_ShowPic;
		LeaveCriticalSection(&g_LockPic);

		if (!show)
			break;

		EnterCriticalSection(&g_LockPic);
		max_num = g_MaxPic;
		LeaveCriticalSection(&g_LockPic);

		if (i >= max_num)
			break;

		EnterCriticalSection(&g_LockPic);
		pic = g_Pic + i;
		DrawImage(&pic->rect, pic->image, pic->ipitch, pic->alpha, pic->apitch);
		LeaveCriticalSection(&g_LockPic);

		i++;
	}

	EnterCriticalSection(&g_LockALv);
	if (g_ShowALv)
	{
		pic = &g_ALvBox;
		DrawImage(&pic->rect, pic->image, pic->ipitch, pic->alpha, pic->apitch);
	}
	LeaveCriticalSection(&g_LockALv);

	EndDraw();
}

static INT OnEnter(VOID)
{
	BOX *box;
	PIC *pic;

	if (g_ShowBox)
	{
		// 按回车随机换色，换方向
		for (INT i = 0; i < g_MaxBox; i++)
		{
			box = g_Box + i;

			EnterCriticalSection(&g_LockBox);
			box->color = RGBA(rand(), rand(), rand(), GetAValue(box->color));
			box->move.cx = rand() % 64 - 32;
			box->move.cy = rand() % 64 - 32;
			LeaveCriticalSection(&g_LockBox);
		}
	}

	if (g_ShowPic)
	{
		// 按回车随机换色，换方向
		for (INT i = 0; i < g_MaxPic; i++)
		{
			pic = g_Pic + i;

			EnterCriticalSection(&g_LockPic);
			pic->color = RGB(rand(), rand(), rand());
			pic->move.cx = rand() % 64 - 32;
			pic->move.cy = rand() % 64 - 32;
			LeaveCriticalSection(&g_LockPic);
		}
	}

	if (g_ShowALv)
	{
		// 按回车随机换色
		EnterCriticalSection(&g_LockALv);
		g_ALvBox.color = RGB(rand(), rand(), rand());
		LeaveCriticalSection(&g_LockALv);
	}

	if (g_ShowPic || g_ShowALv)
		UpdateImage();

	return 0;
}

static INT OnDel(VOID)
{
	if (g_ShowBox)
	{
		EnterCriticalSection(&g_LockBox);
		g_MaxBox = 8;
		LeaveCriticalSection(&g_LockBox);
	}

	if (g_ShowPic)
	{
		EnterCriticalSection(&g_LockPic);
		g_MaxPic = 8;
		LeaveCriticalSection(&g_LockPic);
	}

	return 0;
}

static INT OnSpace(VOID)
{
	BOX *box;
	PIC *pic;
	INT count = 8;

	if (g_ShowBox)
	{
		if (g_MaxBox + count > 1000)
			count = 1000 - g_MaxBox;

		box = g_Box + g_MaxBox;

		for (INT i = 0; i < g_MaxBox; i++, box++)
		{
			*box = g_Box[i];
			box->color = RGBA(rand(), rand(), rand(), GetAValue(box->color));

			box->move.cx = rand() % 64 - 32;
			box->move.cy = rand() % 64 - 32;
		}

		EnterCriticalSection(&g_LockBox);
		g_MaxBox += count;
		LeaveCriticalSection(&g_LockBox);
	}

	if (g_ShowPic)
	{
		if (g_MaxPic + count > 1000)
			count = 1000 - g_MaxPic;

		pic = g_Pic + g_MaxPic;

		for (INT i = 0; i < g_MaxPic; i++, pic++)
		{
			*pic = g_Pic[i];
//			pic->color = RGBA(rand(), rand(), rand(), GetAValue(pic->color));

			pic->move.cx = rand() % 64 - 32;
			pic->move.cy = rand() % 64 - 32;
		}

		EnterCriticalSection(&g_LockPic);
		g_MaxPic+= count;
		LeaveCriticalSection(&g_LockPic);
	}
	return 0;
}

static INT OnF1(VOID)
{
	// 切换显示/隐藏方块
	EnterCriticalSection(&g_LockBox);
	g_ShowBox = !g_ShowBox;
	LeaveCriticalSection(&g_LockBox);
	return 0;
}

static INT OnF2(VOID)
{
	// 切换显示/隐藏图像
	EnterCriticalSection(&g_LockPic);
	g_ShowPic = !g_ShowPic;
	LeaveCriticalSection(&g_LockPic);
	return 0;
}

static INT OnF3(VOID)
{
	// 切换显示/隐藏ALPHA渐变方块
	EnterCriticalSection(&g_LockALv);
	g_ShowALv = !g_ShowALv;
	LeaveCriticalSection(&g_LockALv);
	return 0;
}

static INT OnAltEnter(VOID)
{
	if (FullScreen(!g_FullScr))
		g_FullScr = !g_FullScr;

	return 0;
}

static BOOL OnMinimize(VOID)
{
	return FALSE;
}

static BOOL OnMaximize(VOID)
{
	if (!FullScreen(TRUE))
		return FALSE;

	g_FullScr = TRUE;
	return TRUE;
}

static BOOL OnRestore(VOID)
{
	if (!FullScreen(FALSE))
		return FALSE;

	g_FullScr = FALSE;
	return TRUE;
}

static INT OnTimer(VOID)
{
	BOX box;
	PIC pic;
	RECT rect;
	INT alpha;

	for (INT i = 0; i < g_MaxBox; i++)
	{
		box = g_Box[i];

		rect = box.rect;

		// 预计算移动后的位置
		rect.left += box.move.cx;
		rect.right += box.move.cx;
		rect.top += box.move.cy;
		rect.bottom += box.move.cy;

		// X方向反弹
		if (rect.left < 0 || rect.right >= g_Size.cx)
			box.move.cx = -box.move.cx;

		// Y方向反弹
		if (rect.top < 0 || rect.bottom >= g_Size.cy)
			box.move.cy = -box.move.cy;

		// 计算真正的移动后位置
		box.rect.left += box.move.cx;
		box.rect.right += box.move.cx;
		box.rect.top += box.move.cy;
		box.rect.bottom += box.move.cy;

		// 预计算动态改变后的ALPHA
		alpha = GetAValue(box.color) + box.ac;

		// 变化量反弹
		if (alpha < 0 || alpha > COLOR_AMAX)
			box.ac = -box.ac;

		// 计算真正的动态改变后的ALPHA
		alpha = GetAValue(box.color) + box.ac;

		// 颜色合成
		box.color = RGB2RGBA(box.color, alpha);

		// 写回
		EnterCriticalSection(&g_LockBox);
		g_Box[i] = box;
		LeaveCriticalSection(&g_LockBox);
	}

	for (INT i = 0; i < g_MaxPic; i++)
	{
		pic = g_Pic[i];

		rect = pic.rect;

		// 预计算移动后的位置
		rect.left += pic.move.cx;
		rect.right += pic.move.cx;
		rect.top += pic.move.cy;
		rect.bottom += pic.move.cy;

		// X方向反弹
		if (rect.left < 0 || rect.right >= g_Size.cx)
			pic.move.cx = -pic.move.cx;

		// Y方向反弹
		if (rect.top < 0 || rect.bottom >= g_Size.cy)
			pic.move.cy = -pic.move.cy;

		// 计算真正的移动后位置
		pic.rect.left += pic.move.cx;
		pic.rect.right += pic.move.cx;
		pic.rect.top += pic.move.cy;
		pic.rect.bottom += pic.move.cy;

		// 写回
		EnterCriticalSection(&g_LockPic);
		g_Pic[i] = pic;
		LeaveCriticalSection(&g_LockPic);
	}

	return 0;
}

static INT OnQuit(VOID)
{
	EnterCriticalSection(&g_Lock);
	g_End = TRUE;
	LeaveCriticalSection(&g_Lock);
	WaitForSingleObject(g_Thread, INFINITE);
	PostQuitMessage(0);
	return 0;
}

static VOID InitAlpha(VOID)
{
	INT x, y;
	SIZE size;
	INT laxis[8], saxis[8], lxs[8];

	for (INT i = 0; i < MAX_PIC_NUM; i++)
	{
		// 获取方块大小
		size.cx = g_Pic[i].rect.right - g_Pic[i].rect.left;
		size.cy = g_Pic[i].rect.bottom - g_Pic[i].rect.top;

		// 目前最大仅支持200x200的矩形
		if (size.cx > MAX_PIC_WIDTH || size.cy > MAX_PIC_HEIGHT)
			continue;

		// 椭圆长短轴计算（平方）
		laxis[0] = size.cx * size.cx / 4;
		saxis[0] = size.cy * size.cy / 4;
		laxis[1] = size.cx * size.cx * 49 / 256;
		saxis[1] = size.cy * size.cy * 49 / 256;
		laxis[2] = size.cx * size.cx * 9 / 64;
		saxis[2] = size.cy * size.cy * 9 / 64;
		laxis[3] = size.cx * size.cx * 25 / 256;
		saxis[3] = size.cy * size.cy * 25 / 256;
		laxis[4] = size.cx * size.cx / 16;
		saxis[4] = size.cy * size.cy / 16;
		laxis[5] = size.cx * size.cx * 9 / 256;
		saxis[5] = size.cy * size.cy * 9 / 256;
		laxis[6] = size.cx * size.cx / 64;
		saxis[6] = size.cy * size.cy / 64;
		laxis[7] = size.cx * size.cx / 256;
		saxis[7] = size.cy * size.cy / 256;

		// 放在外边提前计算长短轴平方积以提高效率
		lxs[0] = laxis[0] * saxis[0];
		lxs[1] = laxis[1] * saxis[1];
		lxs[2] = laxis[2] * saxis[2];
		lxs[3] = laxis[3] * saxis[3];
		lxs[4] = laxis[4] * saxis[4];
		lxs[5] = laxis[5] * saxis[5];
		lxs[6] = laxis[6] * saxis[6];
		lxs[7] = laxis[7] * saxis[7];

		// 图像内存临界区
		EnterCriticalSection(&g_LockPic);

		g_Pic[i].image = g_Image[i];
		g_Pic[i].ipitch = MAX_PIC_WIDTH * sizeof(WORD);
		g_Pic[i].alpha = g_Alpha[i];
		g_Pic[i].apitch = MAX_PIC_WIDTH * sizeof(BYTE);

		for (INT j = 0; j < size.cy; j++)
		{
			y = (size.cy - j * 2) / 2;
			for (INT k = 0; k < size.cx; k++)
			{
				x = (k * 2 - size.cx) / 2;
				if (x * x * saxis[0] + y * y * laxis[0] > lxs[0])
					g_Alpha[i][j][k] = 0x00;
				else if (x * x * saxis[1] + y * y * laxis[1] > lxs[1])
					g_Alpha[i][j][k] = 0x7f;
				else if (x * x * saxis[2] + y * y * laxis[2] > lxs[2])
					g_Alpha[i][j][k] = 0xff;
				else if (x * x * saxis[3] + y * y * laxis[3] > lxs[3])
					g_Alpha[i][j][k] = 0x5f;
				else if (x * x * saxis[4] + y * y * laxis[4] > lxs[4])
					g_Alpha[i][j][k] = 0xbf;
				else if (x * x * saxis[5] + y * y * laxis[5] > lxs[5])
					g_Alpha[i][j][k] = 0x3f;
				else if (x * x * saxis[6] + y * y * laxis[6] > lxs[6])
					g_Alpha[i][j][k] = 0x9f;
				else if (x * x * saxis[7] + y * y * laxis[7] > lxs[7])
					g_Alpha[i][j][k] = 0x1f;
				else
					g_Alpha[i][j][k] = 0x7f;
			}
		}

		LeaveCriticalSection(&g_LockPic);
	}

	EnterCriticalSection(&g_LockALv);
	for (INT i = 0; i < 256; i++)
		g_ALvAlpha[0][i] = i;
	for (INT j = 1; j < 256; j++)
		CopyMemory(g_ALvAlpha[j], g_ALvAlpha[0], 256);
	LeaveCriticalSection(&g_LockALv);
}

static VOID UpdateImage(VOID)
{
	INT x, y;
	SIZE size;
	BYTE r, g, b;
	WORD color[5];
	INT laxis[4], saxis[4], lxs[4];

	for (INT i = 0; i < MAX_PIC_NUM; i++)
	{
		// 获取方块大小
		size.cx = g_Pic[i].rect.right - g_Pic[i].rect.left;
		size.cy = g_Pic[i].rect.bottom - g_Pic[i].rect.top;

		// 目前最大仅支持200x200的矩形
		if (size.cx > MAX_PIC_WIDTH || size.cy > MAX_PIC_HEIGHT)
			continue;

#if 1
		// 椭圆长短轴计算（平方）
		laxis[0] = size.cx * size.cx / 4;
		saxis[0] = size.cy * size.cy / 4;
		laxis[1] = size.cx * size.cx * 9 / 64;
		saxis[1] = size.cy * size.cy * 9 / 64;
		laxis[2] = size.cx * size.cx / 16;
		saxis[2] = size.cy * size.cy / 16;
		laxis[3] = size.cx * size.cx / 64;
		saxis[3] = size.cy * size.cy / 64;

		// 放在外边提前计算长短轴平方积以提高效率
		lxs[0] = laxis[0] * saxis[0];
		lxs[1] = laxis[1] * saxis[1];
		lxs[2] = laxis[2] * saxis[2];
		lxs[3] = laxis[3] * saxis[3];

		// 计算插值颜色
		r = GetRValue(g_Pic[i].color);
		g = GetGValue(g_Pic[i].color);
		b = GetBValue(g_Pic[i].color);
		color[0] = COLOR_MAKERGB(0, 0, 0);
		color[1] = COLOR_MAKERGB(r / 4, g / 4, b / 4);
		color[2] = COLOR_MAKERGB(r / 2, g / 2, b / 2);
		color[3] = COLOR_MAKERGB(r * 3 / 4, g * 3 / 4, b * 3 / 4);
		color[4] = COLOR_MAKERGB(r, g, b);

		// 图像内存临界区
		EnterCriticalSection(&g_LockPic);
		for (INT j = 0; j < size.cy; j++)
		{
			y = (size.cy - j * 2) / 2;
			for (INT k = 0; k < size.cx; k++)
			{
				x = (k * 2 - size.cx) / 2;
				if (x * x * saxis[0] + y * y * laxis[0] > lxs[0])
					g_Image[i][j][k] = color[0];
				else if (x * x * saxis[1] + y * y * laxis[1] > lxs[1])
					g_Image[i][j][k] = color[1];
				else if (x * x * saxis[2] + y * y * laxis[2] > lxs[2])
					g_Image[i][j][k] = color[2];
				else if (x * x * saxis[3] + y * y * laxis[3] > lxs[3])
					g_Image[i][j][k] = color[3];
				else
					g_Image[i][j][k] = color[4];
			}
		}
		LeaveCriticalSection(&g_LockPic);
#else
		r = GetRValue(g_Pic[i].color);
		g = GetGValue(g_Pic[i].color);
		b = GetBValue(g_Pic[i].color);
		color[0] = COLOR_MAKERGB(r, g, b);

		// 图像内存临界区
		EnterCriticalSection(&g_LockPic);
		for (INT j = 0; j < size.cy; j++)
		{
			for (INT k = 0; k < size.cx; k++)
			{
				g_Image[i][j][k] = color[0];
			}
		}
		LeaveCriticalSection(&g_LockPic);
#endif
	}

	r = GetRValue(g_ALvBox.color);
	g = GetGValue(g_ALvBox.color);
	b = GetBValue(g_ALvBox.color);
	EnterCriticalSection(&g_LockALv);
	for (INT i = 0; i < 256; i++)
		g_ALvImage[0][i] = COLOR_MAKERGB(r, g, b);
	for (INT j = 1; j < 256; j++)
		CopyMemory(g_ALvImage[j], g_ALvImage[0], 512);
	LeaveCriticalSection(&g_LockALv);
}

static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_TIMER:
		if (wParam == g_Timer)
			return OnTimer();
		break;
	case WM_SYSCOMMAND:
		switch (wParam)
		{
		case SC_MINIMIZE:
			if (OnMinimize())
				return 0;
			break;
		case SC_MAXIMIZE:
			if (OnMaximize())
				return 0;
			break;
		case SC_RESTORE:
			if (OnRestore())
				return 0;
			break;
		}
		break;
	case WM_SYSCHAR:
		if (wParam == VK_RETURN && lParam & 0x20000000)
			return OnAltEnter();
		break;
	case WM_KEYUP:
		switch (wParam)
		{
		case VK_DELETE:
			return OnDel();
		case VK_F1:
			return OnF1();
		case VK_F2:
			return OnF2();
		case VK_F3:
			return OnF3();
		}
		break;
	case WM_CHAR:
		switch (wParam)
		{
		case VK_RETURN:
			return OnEnter();
		case VK_SPACE:
			return OnSpace();
		case VK_ESCAPE:
			PostMessage(hWnd, WM_DESTROY, 0, 0);
			return 0;
		}
		break;
	case WM_DESTROY:
		return OnQuit();
	}

	return DefWindowProc(hWnd, message, wParam, lParam);
}

static DWORD WINAPI DrawThread(LPVOID lpParameter)
{
	BOOL exit;

	for (;;)
	{
		EnterCriticalSection(&g_Lock);
		exit = g_End;
		LeaveCriticalSection(&g_Lock);
		if (exit)
			return 0UL;

		Draw();
	}

	return 0UL;
}

//////////////////////////////////////////////////////////////////////////
